package com.wxjfkg.workflow.impl;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.history.HistoricVariableInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.form.EnumFormType;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fivestar.util.consts.Constants;
import com.fivestar.util.json.JSonUtil;
import com.fivestar.util.str.StringUtils;
import com.fivestar.workflow.ActPtaskAction;
import com.fivestar.workflow.CmsUser;
import com.fivestar.workflow.ProcessTraceVO;
import com.fivestar.workflow.XbkProcessService;
import com.fivestar.workflow.XbkWorkOrderTaskService;
import com.fivestar.xbk.service.vo.XbkWorkOrderTaskDto;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.RuleRunner;
import com.wxjfkg.workflow.CmsUserService;
import com.wxjfkg.ywxt.domain.loan.apply.BaseProcessVO;
import com.wxjfkg.ywxt.domain.loan.apply.ProcessDucumentDto;
import com.wxjfkg.ywxt.domain.loan.apply.ProcessFormDto;

@Service("xbkProcessService")
public class XbkProcessServiceImpl implements XbkProcessService{

	private static final Logger logger = LoggerFactory.getLogger(XbkProcessService.class);
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private IdentityService identityService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private HistoryService historyServie;
	@Autowired
	private FormService formService;
	@Autowired
	private XbkWorkOrderTaskService xbkPersonalTaskService;
    @Autowired
    private ProcessEngineConfiguration processEngineConfiguration;
    @Autowired
    private ProcessEngineFactoryBean processEngine;
	@Autowired
	private CmsUserService userService;
	//规则调度
	private RuleRunner runner = new RuleRunner();
	
	@Transactional(value="txTranManager")
	public String startProcess(String authenticatedUserId,
			List<String> operIds, String processDefinitionKey,
			BaseProcessVO processVO, Map<String, Object> variables)
			throws Exception {
		// 1.用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
		identityService.setAuthenticatedUserId(authenticatedUserId);

		// 2.启动流程实例
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,
						processVO.getBusinessKey(), variables);

		logger.info("启动新的流程实例->" + processInstance.getProcessDefinitionId());

		// 3.发送待办事务
		sendPersonalTasks(processVO.getTaskTitle() ,operIds, processInstance , processVO ,variables);
		return processInstance.getProcessInstanceId();
	}

	@Transactional(value="txTranManager" , propagation = Propagation.REQUIRED)
	public void completeTask(String user_id, String taskId, List<String> operIds ,
			Map<String, Object> variables , BaseProcessVO processVO) throws Exception {
		//完成任务并发送代办信息
		ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
		
		taskService.claim(taskId, user_id);
		taskService.complete(taskId, variables);
		if(!isProcessInstanceEnded(processInstance.getId())){
			sendPersonalTasks(processVO.getTaskTitle() , operIds , processInstance , processVO , variables);
		}
		
		//更新待办信息为已办
		XbkWorkOrderTaskDto zPersonalTasks = new XbkWorkOrderTaskDto();
		zPersonalTasks.setUserId(user_id);
		zPersonalTasks.setTaskId(taskId);
		zPersonalTasks.setOperTime(new Date());
		xbkPersonalTaskService.completeActPersonalTasksVO(zPersonalTasks);
		
		//删除当前环节的其他待办信息
		XbkWorkOrderTaskDto deleteTask = new XbkWorkOrderTaskDto();
		deleteTask.setUserId(user_id);
		deleteTask.setTaskId(taskId);
		xbkPersonalTaskService.deleteActPersonalTasksVO(deleteTask);
	}

	@Override
	public List<ProcessTraceVO> selectProcessTraceList(
			String processInstanceId) {
		List<ProcessTraceVO> resultList = new ArrayList<ProcessTraceVO>();
		if(StringUtils.isEmpty(processInstanceId)){
			return resultList;
		}
		// 查询历史流程实例
		HistoricProcessInstance hpi = this.historyServie.createHistoricProcessInstanceQuery()
								.processInstanceId(processInstanceId).singleResult();
		if(hpi==null){
			return resultList;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		// 设置发起流程节点
		ProcessTraceVO startProcessTrace = new ProcessTraceVO();
		startProcessTrace.setEnd_time(sdf.format(hpi.getStartTime()));

		startProcessTrace.setTaskName("发起流程");
		CmsUser account = new CmsUser();
		if (StringUtils.isNotEmpty(hpi.getStartUserId())) {
			account.setUserName(hpi.getStartUserId());
			account = userService.queryUserByUserName(account.getUserName());
		}

		startProcessTrace.setOperater(account.getUserName());
		startProcessTrace.setDepartment(account.getDepartment());
		// 创建流程实例变量的查询对象
		HistoricVariableInstanceQuery historyVarQuery = this.historyServie
				.createHistoricVariableInstanceQuery().processInstanceId(
						processInstanceId);

		
		HistoricVariableInstance address = historyVarQuery.variableName("address").singleResult();
		startProcessTrace.setAddress((address==null||address.getValue()==null)? "":address.getValue().toString());
		resultList.add(startProcessTrace);

		// 查询历史任务列表
		List<HistoricTaskInstance> list = this.historyServie
				.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId).orderByTaskCreateTime()
				.asc().list();
		for (HistoricTaskInstance tmp : list) {
			ProcessTraceVO tmpProcessTrace = new ProcessTraceVO();
			tmpProcessTrace.setStart_time(sdf.format(tmp.getStartTime()));
			
			HistoricVariableInstance var = null;
			if(historyVarQuery!=null){
				var = historyVarQuery.variableName(
						tmp.getTaskDefinitionKey() + "_action").singleResult();
			}
			HistoricVariableInstance var2 = null;
			if(historyVarQuery!=null){
				var2 = historyVarQuery.variableName(
						tmp.getTaskDefinitionKey() + "_option").singleResult();
			}
			HistoricVariableInstance var3 = null;
			if(historyVarQuery!=null){
				var3 = historyVarQuery.variableName(
						tmp.getTaskDefinitionKey() + "_address").singleResult();
			}

			if (tmp.getEndTime() != null) { // 如果任务已经结束
				account = new CmsUser();
				tmpProcessTrace.setEnd_time(sdf.format(tmp.getEndTime()));
				if (StringUtils.isNotEmpty(tmp.getAssignee())) {
					account.setUserName(tmp.getAssignee());
					account = userService.queryUserByUserName(account.getUserName());
					tmpProcessTrace.setOperater(account.getUserName());
					tmpProcessTrace.setDepartment(account.getDepartment());
				}
			} else { // 如果任务尚未结束
				List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(tmp.getId());
				StringBuffer operaterId = new StringBuffer();
				for (IdentityLink tmpIL : identityLinkList) {
					operaterId.append(tmpIL.getUserId() + ",");
				}
				if (operaterId.length() != 0) {
					tmpProcessTrace.setOperater(operaterId.substring(0,
							operaterId.length() - 1));
				}
			}
			tmpProcessTrace.setTaskName(tmp.getName());
			tmpProcessTrace.setAction((var == null||var.getValue()==null)? "" : var.getValue().toString());
			tmpProcessTrace.setOption((var2 == null||var2.getValue()==null)? "" : var2.getValue().toString());
			tmpProcessTrace.setAddress((var3==null||var3.getValue()==null)? "" : var3.getValue().toString());
			
			resultList.add(tmpProcessTrace);
		}

		logger.info("查询文字流程跟踪->" + resultList);
		return resultList;
	}

	/**
	 * 生成待办信息
	 * @param taskTitle
	 * @param operIds
	 * @param processInstance
	 */
	private void sendPersonalTasks(String taskTitle, List<String> operIds,
			ProcessInstance processInstance ,BaseProcessVO processVO, Map<String, Object> variables) throws Exception{
		if (processInstance.isEnded()) {
			throw new Exception("该流程实例已结束，无法发布待办任务！");
		}
		ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByProcessInstanceId(processInstance.getProcessInstanceId());
		
		List<Task> taskList = findTaskByProcessInstanceId(processInstance
				.getProcessInstanceId());
		for (Task task : taskList) {
			XbkWorkOrderTaskDto personalTask = new XbkWorkOrderTaskDto();

			personalTask.setProcessInstanceId(processInstance.getProcessInstanceId());// 设置流程编号
			personalTask.setStatus("0");// 设置任务状态
			
			String taskContent = null;
			if(variables != null && !variables.isEmpty()){
				//设置任务标题
				for(Entry<String, Object> entry : variables.entrySet()){
					String key = entry.getKey();
					if(key.contains("_action")){
						taskContent = (String) entry.getValue();
					}
				}
			}
			personalTask.setTaskContent(taskContent != null ? taskContent : task.getName());// 设置流程节点名
			personalTask.setTaskTitle(taskTitle);
			personalTask.setReserveField1(processVO.getReserveField1());
			personalTask.setReserveField2(processVO.getReserveField2());
			personalTask.setReserveField3(processVO.getReserveField3());
			personalTask.setTaskId(task.getId());// 设置任务节点Id
			personalTask.setTaskKey(task.getTaskDefinitionKey());// 设置任务节点key
			personalTask.setProcessKey(processDefinition.getKey());// 设置流程key
			personalTask.setTaskStatus(Constants.PersonalTaskStatus.zero);// 0：任务未领取；1：已领取待办；2：已办
			personalTask.setCreateTime(new Date());
			
			List<ActPtaskAction> opts = findNextOptCode(task.getId() , processVO);
			if(operIds != null){
				//手动分配下个环节处理用户信息
				for (String operId: operIds) {
					if (!StringUtils.isEmpty(operId)) {
						taskService.addCandidateUser(task.getId() , operId);
					}
				}
			}
			// 取得当前任务的候选用户列表
			List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());

			if(identityLinkList == null || identityLinkList.isEmpty()){
				//退回重新处理,设置处理人信息
				XbkWorkOrderTaskDto bTask = new XbkWorkOrderTaskDto();
				bTask.setTaskStatus(Constants.PersonalTaskStatus.two);
				bTask.setProcessInstanceId(personalTask.getProcessInstanceId());
				bTask.setTaskKey(task.getTaskDefinitionKey());
				bTask = xbkPersonalTaskService.selectXbkWorkOrderTaskDto(bTask);
				if(bTask != null){
					taskService.setAssignee(task.getId() , bTask.getUserId());
					identityLinkList = taskService.getIdentityLinksForTask(task.getId());
				}
			}
			
			for (IdentityLink tmp : identityLinkList) {
				if (!StringUtils.isEmpty(tmp.getUserId())) {
					personalTask.setUserId(tmp.getUserId());// 设置所属用户
					boolean exists = xbkPersonalTaskService.isPersonalTaskExists(personalTask);
					if(!exists){
						xbkPersonalTaskService.saveXbkPersonalTasksVO(personalTask);
					}else{
						continue;
					}
					for(ActPtaskAction opt : opts){
						opt.setPersonalTaskId(personalTask.getPersonalTaskId().toString());
					}
					if(opts!=null && !opts.isEmpty()){
						logger.info("保存ActPtaskAction信息");
						xbkPersonalTaskService.insertActPtaskAction(opts);
					}
					logger.info("发布" + task.getName() + "任务到候选用户个人待办任务，用户编号 -> " + tmp.getUserId()+ "，标题->" + taskTitle);
				}
			}
			
			if(identityLinkList == null || identityLinkList.isEmpty()){
				logger.error("发布" + task.getName() + "任务失败,未设置处理人信息!");
			}
			//获取配置的表单信息
			List<ProcessFormDto> fromList = getFormPropertiesByTaskId(task.getId() , processInstance.getProcessInstanceId());
			for(ProcessFormDto from : fromList){
				//保存表单信息
				ProcessFormDto formExist = xbkPersonalTaskService.selectTaskProcessForm(from);
				if(formExist==null){
					//避免重复
					xbkPersonalTaskService.saveProcessForm(from);
				}
			}
		}
	}
	
	public ProcessDefinitionEntity findProcessDefinitionEntityByProcessInstanceId(
			String processInstanceId) throws Exception {
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getProcessDefinition(selectProcessInstanceByProcessInstanceId(
						processInstanceId).getProcessDefinitionId());

		if (processDefinition == null) {
			throw new Exception("流程定义未找到!");
		}
		return processDefinition;
	}
	
	/**
	 * 根据流程实例编号获取流程实例
	 * 
	 * @param processInstanceId
	 * @return
	 */
	public ProcessInstance selectProcessInstanceByProcessInstanceId(
			String processInstanceId) {
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		return processInstance;
	}
	
	/**
	 * 根据流程实例id查找任务实例
	 * 
	 * @param processInstanceId
	 * @return
	 * @throws Exception
	 */
	public List<Task> findTaskByProcessInstanceId(String processInstanceId)
			throws Exception {
		List<Task> taskList = this.taskService.createTaskQuery()
				.processInstanceId(processInstanceId).list();
		if (taskList == null || taskList.size() == 0) {
			throw new Exception("任务实例未找到!");
		}
		return taskList;
	}
	
	/**
	 * 获取当前任务后续的操作信息
	 * @param taskId
	 * @return
	 * @throws Exception 
	 */
	private List<ActPtaskAction> findNextOptCode(String taskId , BaseProcessVO processVO) throws Exception{
		Task task = this.findTaskById(taskId);
		String type = "";
		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(task.getProcessDefinitionId());

		List<ActivityImpl> activitiList = def.getActivities();

		String excId = task.getExecutionId();
		ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(excId).singleResult();
		String activitiId = execution.getActivityId();
		
		List<ActPtaskAction> list = new ArrayList<ActPtaskAction>();
		for (ActivityImpl activityImpl : activitiList) {
			String id = activityImpl.getId();
			if (activitiId.equals(id)) {
				logger.info("当前任务：" + activityImpl.getProperty("name")); // 输出某个节点的某种属性
				
				List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();// 获取从某个节点出来的所有线路
				
				for (PvmTransition tr : outTransitions) {
					PvmActivity ac = tr.getDestination(); // 获取线路的终点节点
					logger.info("下一步任务任务：" + ac.getProperty("name"));
					type = ac.getProperty("type").toString();
					if ("exclusiveGateway".equals(type)) {
						// 获取分支节点
						List<PvmTransition> pvms = ac.getOutgoingTransitions();
						for (PvmTransition pvm : pvms) {
							ActPtaskAction taskOpt = new ActPtaskAction();
							String documentation = (String) pvm.getProperty("documentation");
							String name = (String) pvm.getProperty("name");
							String flowId = pvm.getId();
							taskOpt.setName(name);
							taskOpt.setValue(flowId);
							taskOpt.setCode(id);
							taskOpt.setDocumentJson(documentation);
							taskOpt.setTaskId(taskId);
							boolean b = qlExpressRun(documentation , processVO);
							if(b){
								list.add(taskOpt);
							}
						}
					} else {
						ActPtaskAction taskOpt = new ActPtaskAction();
						
						String name = (String) tr.getProperty("name");
						String flowId = tr.getId();
						taskOpt.setName(name);
						taskOpt.setValue(flowId);
						taskOpt.setCode(id);
						taskOpt.setTaskId(taskId);
						list.add(taskOpt);
					}
					break;
				}
				break;
			}
		}
		return list;
	}
	
	/**
	 * 通过QlExpress判断是否执行
	 * @param documentation
	 * @param processVO
	 * @return true:执行;false:不执行
	 */
	private boolean qlExpressRun(String documentation , BaseProcessVO processVO) {
		if(StringUtils.isEmpty(documentation)){
			return true;
		}
		try {
			if(processVO != null){
				//设置上下午
				IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
				Class<? extends BaseProcessVO> entityClass = processVO.getClass();
				Field[] fields = entityClass.getDeclaredFields();
				for(Field f : fields){
					f.setAccessible(true); //设置些属性是可以访问的
					Object val = f.get(processVO);//得到此属性的值 
					if(val != null && StringUtils.isNotEmpty(val.toString())){
						expressContext.put(f.getName() , val);
					}
				}
				return runner.run(documentation , expressContext);
			}
		} catch (Exception e) {
			logger.error("规则调度失败" , e);
		}
		return false;
	}
	
	public TaskEntity findTaskById(String taskId) throws Exception {
		TaskEntity task = (TaskEntity) taskService.createTaskQuery()
				.taskId(taskId).singleResult();
		if (task == null) {
			throw new Exception("任务实例未找到!");
		}
		return task;
	}
	
	/** 
     * 根据任务ID获取对应的流程实例 
     *  
     * @param taskId 
     *            任务ID 
     * @return 
     * @throws Exception 
     */  
    public ProcessInstance findProcessInstanceByTaskId(String taskId)  
            throws Exception {  
        // 找到流程实例  
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(  
                        findTaskById(taskId).getProcessInstanceId())  
                .singleResult();  
        if (processInstance == null) {   
            throw new Exception("流程实例未找到!");  
        }  
        return processInstance;  
    }
    
	@Override
	public String getBusinessKeyByTaskId(String taskId) {
		try {
			ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
			if(processInstance != null){
				return processInstance.getBusinessKey();
			}
		} catch (Exception e) {
			logger.error("根据任务ID获取对应的流程实例失败" , e);
		}
		return "";
	}
	
    /**
     * 判断流程是否已结束
     * @param processInstanceId
     * @return true 是，false 否
     */
    public boolean isProcessInstanceEnded(String processInstanceId) {
    	List<HistoricProcessInstance> resultList = this.historyServie.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
    	return resultList.size() == 0;
    }
    
    /**
     * 查找当前流程实例的任务ID
     */
	@Override
	public List<String> getCurrentTaskIdByProcessInstanceId(String processInstanceId) {
		List<String> taskIds = new ArrayList<String>();
		try {
			if(!isProcessInstanceEnded(processInstanceId)){
				List<Task> tasks = findTaskByProcessInstanceId(processInstanceId);
				for(Task task:tasks){
					taskIds.add(task.getId());
				}
			}
		} catch (Exception e) {
			logger.error("查找当前流程实例的任务ID失败" , e);
		}
		return taskIds;
	}
	
	/**
	 * 生成流程跟踪图片
	 * @param taskId 包含：任务id
	 * @return
	 * @throws Exception 
	 */
	@Override
	public byte[] generateProcessTraceDiagram(String taskId) throws Exception {
		TaskEntity task = findTaskById(taskId);
		String processInstanceId = task.getProcessInstanceId();
		//获取历史流程实例
        HistoricProcessInstance processInstance =  historyServie.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());

        List<HistoricActivityInstance> highLightedActivitList =  historyServie.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        //高亮环节id集合
        List<String> highLightedActivitis = new ArrayList<String>();
        //高亮线路id集合
        List<String> highLightedFlows = getHighLightedFlows(definitionEntity,highLightedActivitList);

        for(HistoricActivityInstance tempActivity : highLightedActivitList){
            String activityId = tempActivity.getActivityId();
            highLightedActivitis.add(activityId);
        }

        //中文显示的是口口口，设置字体就好了
        InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis,highLightedFlows,"宋体","宋体",null,1.0);
		
        return IOUtils.toByteArray(imageStream);
	}
	
	/**
     * 获取需要高亮的线
     * @param processDefinitionEntity
     * @param historicActivityInstances
     * @return
     */
    private List<String> getHighLightedFlows(
            ProcessDefinitionEntity processDefinitionEntity,
            List<HistoricActivityInstance> historicActivityInstances) {
        List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 对历史流程节点进行遍历
            ActivityImpl activityImpl = processDefinitionEntity
                    .findActivity(historicActivityInstances.get(i)
                            .getActivityId());// 得到节点定义的详细信息
            List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用以保存后需开始时间相同的节点
            ActivityImpl sameActivityImpl1 = processDefinitionEntity
                    .findActivity(historicActivityInstances.get(i + 1)
                            .getActivityId());
            // 将后面第一个节点放在时间相同节点的集合里
            sameStartTimeNodes.add(sameActivityImpl1);
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                HistoricActivityInstance activityImpl1 = historicActivityInstances
                        .get(j);// 后续第一个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances
                        .get(j + 1);// 后续第二个节点
                if (activityImpl1.getStartTime().equals(
                        activityImpl2.getStartTime())) {
                    // 如果第一个节点和第二个节点开始时间相同保存
                    ActivityImpl sameActivityImpl2 = processDefinitionEntity
                            .findActivity(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {
                    // 有不相同跳出循环
                    break;
                }
            }
            List<PvmTransition> pvmTransitions = activityImpl
                    .getOutgoingTransitions();// 取出节点的所有出去的线
            for (PvmTransition pvmTransition : pvmTransitions) {
                // 对所有的线进行遍历
                ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition
                        .getDestination();
                // 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;
    }

	@Override
	public String findNextStepType(String taskId, List<ProcessDucumentDto> list)
			throws Exception {
		Task task = this.findTaskById(taskId);
    	String type = "";
    	ProcessDefinitionEntity def = 
    			(ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());  

    	List<ActivityImpl> activitiList = def.getActivities();

    	String excId = task.getExecutionId();  
    	ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(excId).singleResult();  
    	String activitiId = execution.getActivityId();  

    	for(ActivityImpl activityImpl:activitiList){  
    		String id = activityImpl.getId();  
    		if(activitiId.equals(id)){  
    			logger.info("当前任务："+activityImpl.getProperty("name")); //输出某个节点的某种属性  
    			List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();//获取从某个节点出来的所有线路  
    			for(PvmTransition tr : outTransitions){  
    				PvmActivity ac = tr.getDestination(); //获取线路的终点节点  
    				logger.info("下一步任务任务：" + ac.getProperty("name")); 
    				type = ac.getProperty("type").toString();
    				if("exclusiveGateway".equals(type)){
    					//获取分支节点
    					List<PvmTransition> pvms = ac.getOutgoingTransitions();
    					for(PvmTransition pvm : pvms){
    						ProcessDucumentDto doc = new ProcessDucumentDto();
    						String documentation = (String) pvm.getProperty("documentation");
    						if(StringUtils.isNotEmpty(documentation)){
    							doc = JSonUtil.toBean(documentation , ProcessDucumentDto.class);
    						}
    						String name = (String) pvm.getProperty("name");
    						String flowId = pvm.getId();
    						doc.setName(name);
    						doc.setFlowId(flowId);
    						list.add(doc);
    					}
    				}else{
    					String documentation = (String) tr.getProperty("documentation");
						if(StringUtils.isNotEmpty(documentation)){
							ProcessDucumentDto doc = JSonUtil.toBean(documentation , ProcessDucumentDto.class);
							list.add(doc);
						}
    				}
    				break;
    			}  
    			break;
    		}
    	}
    	return type;
	}
	
	/**
	 * 关联业务对象与流程对象
	 * @param baseProcess
	 * @return
	 */
	public BaseProcessVO mapBusiness2Process(BaseProcessVO baseProcess) {
		//1.根据processInstanceId在HistoryService中查找最后一个HistoryTask
		List<HistoricTaskInstance> historicTaskList;
		if(StringUtils.isEmpty(baseProcess.getTk_id())) {
			historicTaskList = 
					this.findHistoricTaskListByProcessInstanceId(baseProcess.getProcessInstanceId());			
		} else {
			historicTaskList = 
					this.historyServie.createHistoricTaskInstanceQuery().processInstanceId(baseProcess.getProcessInstanceId()).taskId(baseProcess.getTk_id()).orderByHistoricTaskInstanceEndTime().desc().list();
		}
		HistoricProcessInstance hpi = 
				this.historyServie.createHistoricProcessInstanceQuery().processInstanceId(baseProcess.getProcessInstanceId()).singleResult();
		HistoricTaskInstance historicTask = historicTaskList.get(historicTaskList.size() - 1);
		
		baseProcess.setTk_id(historicTask.getId());
		baseProcess.setTk_name(historicTask.getName());
		baseProcess.setBusinessKey(hpi.getBusinessKey());
		baseProcess.setIsProcessEnded(hpi.getEndTime() == null?"false":"true");
		
		//2.根据processDefinitionId找到processDefinitionKey
		ProcessDefinition processDefinition =
				this.repositoryService.createProcessDefinitionQuery().processDefinitionId(historicTask.getProcessDefinitionId()).singleResult();
		baseProcess.setProcessDefinitionId(processDefinition.getId());
		baseProcess.setProcess_key(processDefinition.getKey());
		baseProcess.setProcess_name(processDefinition.getName());
		return baseProcess;
	}
	
	/**
	 * 根据流程实例id查找历史任务实例列表（按结束时间排序）
	 * @param processInstanceId
	 * @return
	 */
	private List<HistoricTaskInstance> findHistoricTaskListByProcessInstanceId(String processInstanceId) {
		return this.historyServie.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
	}

	/**
	 * 获取任务表单
	 * @param taskId
	 * @return
	 */
	private List<ProcessFormDto> getFormPropertiesByTaskId(String taskId , String processInstanceId){
		TaskFormData taskFormData = formService.getTaskFormData(taskId);
		List<ProcessFormDto> list = new ArrayList<ProcessFormDto>();
		if(taskFormData != null){
			List<FormProperty> taskFormProperties = taskFormData.getFormProperties();
			for(FormProperty form : taskFormProperties){
				ProcessFormDto f = new ProcessFormDto();
				f.setProcessInstanceId(processInstanceId);
				f.setTaskId(taskId);
				f.setId(form.getId());
				f.setName(form.getId());
				f.setLabel(form.getName());
				f.setValue(form.getValue());
				f.setCreatetime(new Date());
				//设置value信息
				if(form.getType()!=null &&
					form.getType() instanceof EnumFormType){
					EnumFormType enumValue = (EnumFormType) form.getType() ;
					@SuppressWarnings("unchecked")
					Map<String, String> values = (Map<String, String>) enumValue.getInformation("values");
					String rule = values.get("rule");
					f.setRule(rule);
					String message = values.get("message");
					f.setMessage(message);
					String tableName = values.get("tableName");
					f.setTableName(tableName);
					String fieldName = values.get("fieldName");
					f.setFieldName(fieldName);
					String pkId = values.get("pkId");
					f.setPkField(pkId);
				}
				f.setRequired(String.valueOf(form.isRequired()));
				list.add(f);
			}
		}
		return list;
	}

	@Override
	public String getTaskFormKey(String taskId) {
		TaskFormData formData = formService.getTaskFormData(taskId);
		if(formData != null){
			String formKey = formData.getFormKey();
			return formKey;
		}
		return null;
	}
	
}
